/// @tags: NodeDivideTree
#include <cstdio>
#include <iostream>
#include <vector>

using namespace std;

namespace BlueQuantum {

typedef pair<int, int> pii;

int const N = 2e5 + 5, BIT = 19, INF = 1e9, T = 3e6;

int heads[N], e_cnt;
int n, m, typ;
vector<int> g[N];

struct Edge {
  int to, pre, w;
} e[N * 2];

inline void add_edge(int u, int v, int w) {
  e[++e_cnt].to = v, e[e_cnt].w = w, e[e_cnt].pre = heads[u], heads[u] = e_cnt;
}
inline void build_edge(int u, int v, int w) { add_edge(u, v, w), add_edge(v, u, w); }

namespace ThreeDegreeOptimization {

int son[N], wf[N];

int build(int x, int fa, int &nc) {
  int cnt = 0, c;
  for (int i = 0; i <= (int)g[x].size() - 1; ++i)
    if (g[x][i] ^ fa) build(g[x][i], x, nc);
  for (int i = 0; i <= (int)g[x].size() - 1; ++i)
    if (g[x][i] ^ fa) son[++cnt] = g[x][i], wf[cnt] = 1;
  while (cnt > 2) {
    for (int i = (c = 0) + 1; i <= cnt / 2; ++i)
      nc++, build_edge(nc, son[i * 2 - 1], wf[i * 2 - 1]),
          build_edge(nc, son[i << 1], wf[i << 1]), son[++c] = nc, wf[c] = 0;
    if (cnt & 1) son[++c] = son[cnt], wf[c] = wf[cnt];
    cnt = c;
  }
  for (int i = 1; i <= cnt; ++i) build_edge(x, son[i], wf[i]);
  return 0;
}

}  // namespace ThreeDegreeOptimization

namespace PersistedSegmentTree {

int const T = 3e7, M = 1e5;
int ls[T], rs[T], val[T], s[T], seg_cnt;

inline int init() { return val[0] = INF; }

inline int update(int &x, int y, int p, int v, int l = 0, int r = M) {
  x = ++seg_cnt, ls[x] = ls[y], rs[x] = rs[y], s[x] = s[y];
  int mid = (l + r) >> 1;
  if (l == r) return s[x] += v, val[x] = (s[x] ? l : INF);
  p <= mid ? update(ls[x], ls[y], p, v, l, mid) : update(rs[x], rs[y], p, v, mid + 1, r);
  return val[x] = min(val[ls[x]], val[rs[x]]);
}

inline int query(int x) { return val[x]; }

}  // namespace PersistedSegmentTree
using PersistedSegmentTree::query;
using PersistedSegmentTree::update;

struct Node {
  int g[3], rt[3], c, ans0;
  Node() { g[0] = g[1] = g[2] = rt[0] = rt[1] = rt[2] = c = ans0 = 0; }

  inline int upd_from(Node const &t, int dir, int dis, int sgn) {
    c = t.c;
    for (int i = 0; i <= c - 1; ++i) g[i] = t.g[i], rt[i] = t.rt[i];
    return ans0 = t.ans0, update(rt[dir], t.rt[dir], dis, sgn);
  }

  inline int ans(int k) const {
    int ans = INF;
    if (ans0) return 0;
    for (int i = 0; i <= c - 1; ++i)
      if (i ^ k) ans = min(ans, query(rt[i]));
    return ans;
  }
};

namespace EdgeDividedTree {

Node t[T];
int siz[N], Lst[N], Lcnt, dir[N], d[N], vis[N];
int dis[BIT][N], fr[BIT][N], rt[N], dfz_node_cnt;

inline int getSize(int x, int fa = 0) {
  siz[x] = 1, Lst[++Lcnt] = x;
  for (int i = heads[x], y; i; i = e[i].pre)
    if (!vis[y = e[i].to] && e[i].to != fa) siz[x] += getSize(y, x);
  return siz[x];
}

inline int getRoot(int &x) {
  for (int i = 1, fsz = siz[x], tsz = fsz; i <= Lcnt; ++i) {
    int y = Lst[i], ysz = fsz - siz[y];
    for (int j = heads[y], z; j; j = e[j].pre)
      if (!vis[z = e[j].to] && siz[e[j].to] < siz[y]) ysz = max(ysz, siz[z]);
    if (ysz < tsz) tsz = ysz, x = y;
  }
  return 0;
}

int calc(int x, int fa, int c, int d, int *dis, int *fr) {
  dis[x] = d, fr[x] = c;
  for (int i = heads[x], y; i; i = e[i].pre)
    if (!vis[y = e[i].to] && e[i].to != fa) calc(y, x, c, d + e[i].w, dis, fr);
  return 0;
}

int solve(int x, int dpt = 0) {
  Lcnt = 0, getSize(x), getRoot(x), vis[x] = true, d[x] = dpt;
  int cnt = 0;
  for (int i = heads[x], v; i; i = e[i].pre)
    if (!vis[v = e[i].to]) calc(v, x, cnt++, e[i].w, dis[dpt], fr[dpt]);
  for (int i = heads[x], v; i; i = e[i].pre)
    if (!vis[v = e[i].to]) t[x].g[t[x].c++] = solve(v, dpt + 1);
  return x;
}

inline int getFa(int x) {
  for (int i = d[x] - 1; i >= 0; i--) dir[i] = fr[i][x];
  return d[x];
}

inline int upd(int x, int las, int cur, int sgn) {
  int r = rt[las], len = getFa(x), p = rt[cur] = ++dfz_node_cnt;
  for (int i = 0; i <= len - 1; ++i)
    t[p].upd_from(t[r], dir[i], dis[i][x], sgn), r = t[r].g[dir[i]],
                                                 p = t[p].g[dir[i]] = ++dfz_node_cnt;
  return t[p] = t[r], t[p].ans0 ^= 1;
}

inline int query(int x, int cur) {
  int ans = INF, p = rt[cur], len = getFa(x);
  for (int i = 0; i <= len - 1; ++i)
    ans = min(ans, dis[i][x] + t[p].ans(fr[i][x])), p = t[p].g[dir[i]];
  return min(ans, t[p].ans(-1));
}

}  // namespace EdgeDividedTree
using EdgeDividedTree::query;
using EdgeDividedTree::solve;
using EdgeDividedTree::upd;

namespace StatusSegmentTree {

int ls[T], rs[T], v[T], n, rt[N], n_cnt;

inline int build(int &x, int l, int r) {
  x = ++n_cnt;
  int mid = (l + r) >> 1;
  if (l == r) return v[x] = -1;
  return build(ls[x], l, mid), build(rs[x], mid + 1, r);
}

int build(int _n) { return n = _n, build(rt[0], 1, n); }

int update(int &x, int y, int l, int r, int p) {
  x = ++n_cnt;
  int mid = (l + r) >> 1;
  ls[x] = ls[y], rs[x] = rs[y], v[x] = v[y];
  if (l == r) return v[x] *= -1;
  return p <= mid ? update(ls[x], ls[y], l, mid, p) : update(rs[x], rs[y], mid + 1, r, p);
}

inline int upd_sta(int p, int x, int y) { return update(rt[y], rt[x], 1, n, p); }

}  // namespace StatusSegmentTree
using StatusSegmentTree::upd_sta;

inline int main() {
  cin >> typ >> n;
  for (int i = 1, u, v; i < n; ++i) {
    cin >> u >> v;
    g[u].push_back(v), g[v].push_back(u);
  }
  PersistedSegmentTree::init();
  ThreeDegreeOptimization::build(1, 0, n);
  StatusSegmentTree::build(n);
  EdgeDividedTree::rt[0] = solve(1), EdgeDividedTree::dfz_node_cnt = n;
  cin >> m;
  for (int opt, x, ans = 0, cur = 0, t = 0; m; m--) {
    cin >> opt >> x;
    x ^= (ans * typ);
    switch (opt) {
      case 1:
        t++, upd(x, cur, t, upd_sta(x, cur, t)), cur = t;
        break;
      case 2:
        cout << (ans = query(x, cur)) << '\n';
        break;
      case 3:
        cur = x;
    }
  }
  return 0;
}

}  // namespace BlueQuantum

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("yygq.in", "r", stdin);
  freopen("yygq.out", "w", stdout);
#endif
#endif

  ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
  return BlueQuantum::main();
}
